package com.ddwl.message.service;

import com.ddwl.common.constant.BaseEnum;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.util.StrUtil;
import com.ddwl.common.constant.Constant;
import com.ddwl.common.constant.MessageReceiveTypeEnum;
import com.ddwl.common.feign.api.UserApi;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.MySqlUtil;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.message.constant.MessageConstant;
import com.ddwl.message.dao.MessageInfoDao;
import com.ddwl.message.dao.MessageUserDao;
import com.ddwl.message.model.MessageInfo;
import com.ddwl.message.model.MessageUser;
import com.ddwl.message.model.MessageUserList;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.gate.MessageInfoBo;
import com.ddwl.schema.bo.gate.MessageInfoCreateBo;
import com.ddwl.schema.bo.gate.MessageUserBo;
import com.ddwl.schema.bo.user.UserSearchBo;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.base.RestVo;
import com.ddwl.schema.vo.gate.*;
import com.ddwl.schema.vo.user.UserLevelVo;
import com.ddwl.schema.vo.user.UserVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MessageNoticeService {

    @Autowired
    private MessageInfoDao messageInfoDao;
    @Autowired
    private MessageUserDao messageUserDao;
    @Autowired
    private UserApi userApi;
    @Resource
    private MessagePushService messagePushService;


    /**
     * 消息配置列表
     */
    public PageVo<MessageInfoVo> getList(PageBo<MessageInfoBo> bo) {
        PageHelper.startPage(bo.getPage(), bo.getPageSize(), MySqlUtil.orderBy(bo.getSort(), bo.isAsc()));
        List<MessageInfo> infos = messageInfoDao.select(BeanConverUtils.convertBean(bo.getParam(), MessageInfo.class));
        PageInfo<MessageInfo> pageInfo = new PageInfo<>(infos);
        List<MessageInfoVo> messageInfoVos = BeanConverUtils.convertBeanList(pageInfo.getList(), MessageInfoVo.class);
        return new PageVo<>(pageInfo.getTotal(), bo.getPage(), bo.getPageSize(),messageInfoVos);
    }

    /**
     * 创建消息配置模板
     *
     * @param bo
     */
    @Transactional(rollbackFor = Exception.class)
    public void createMessage(MessageInfoCreateBo bo){
        if(bo.getPushTime()==null){
            bo.setPushTime(Instant.now());
        }
        MessageInfo messageInfo = BeanConverUtils.convertBean(bo, MessageInfo.class);
        messageInfo.setId(UUIDGenerator.getShortUUID());
        messageInfoDao.insert(messageInfo);
        //所有用户
        if (MessageReceiveTypeEnum.ALL.getCode().equals(bo.getType())) {
            ((MessageNoticeService) AopContext.currentProxy()).sentMsg(messageInfo,null,null,null);
        }
        //区域经理
        if (MessageReceiveTypeEnum.AREA.getCode().equals(bo.getType())) {
            ((MessageNoticeService) AopContext.currentProxy()).sentMsg(messageInfo,null,Constant.Area,null);
        }
        //如果发送对象是各级会员
        if (MessageReceiveTypeEnum.SIVER_MEMBER.getCode().equals(bo.getType())
                ||MessageReceiveTypeEnum.GOLD_MEMBER.getCode().equals(bo.getType())
                ||MessageReceiveTypeEnum.DIMOND_MEMBER.getCode().equals(bo.getType())){
            UserLevelVo userLevelVo = userApi.getByUserLevelCode(bo.getType()).getResult();
            if (userLevelVo != null) {
                ((MessageNoticeService) AopContext.currentProxy()).sentMsg(messageInfo,null,null,userLevelVo.getId());
            }
        }
        if (MessageReceiveTypeEnum.APPOINT.getCode().equals(bo.getType())) {
            List<String> userIds=bo.getUserList().stream().map(MessageUserBo::getUserId).collect(Collectors.toList());
            ((MessageNoticeService) AopContext.currentProxy()).sentMsg(messageInfo,userIds,null,null);
        }
    }
    @Async
    public void sentMsg(MessageInfo messageInfo,List<String> ids,Integer type,String levelId) {
        PageBo<UserSearchBo> pageBo = createUserPageBo(ids,type,levelId);
        RestVo<PageVo<UserVo>> userPage = userApi.getUserPage(pageBo);
        PageVo<UserVo> pageVo = userPage.getResult();
        Long total = pageVo.getTotal();
        HashSet<String> cidSet = new HashSet<>();
        insertMessageUser(messageInfo, pageVo.getData(),cidSet);
        int eachSize = pageBo.getPageSize();
        if (total > eachSize) {
            long totalPage = total % eachSize == 0 ? total / eachSize : (total / eachSize) + 1;
            for (int i = 0; i < totalPage-1; i++) {
                pageBo.setPage(i + 2);
                PageVo<UserVo> userPage1 =userApi.getUserPage(pageBo).getResult();
                insertMessageUser(messageInfo, userPage1.getData(),cidSet);
            }
        }
        if (MessageConstant.PUSH.equals(messageInfo.getPush()) && MessageReceiveTypeEnum.ALL.getCode().equals(messageInfo.getType()) && messageInfo.getPushTime().compareTo(Instant.now()) <= 0) {
            pushMessageToApp(messageInfo.getTitle(),messageInfo.getMessageAbstract(),String.format(MessageConstant.PushIntentEnum.MESSAGE_DETAIL.getIntentUrl(), messageInfo.getId()));
        }
    }



    public void insertMessageUser(MessageInfo messageInfo, List<UserVo> userVoList,HashSet<String> cidSet) {
        List<MessageUser> messageUsers = new ArrayList<>();
        List<String> cIds = new ArrayList<>();
        for (UserVo userVo : userVoList) {
            MessageUser messageUser=new MessageUser();
            messageUser.setId(UUIDGenerator.getShortUUID());
            messageUser.setUserId(userVo.getId());
            messageUser.setUserName(userVo.getNickname());
            messageUser.setUserPhone(userVo.getMobile());
            messageUser.setMessageInfoId(messageInfo.getId());
            messageUser.setReadStatus(BaseEnum.ReadEnum.UNREAD.getCode());
            messageUser.setDflag(0);
            messageUser.setGmtCreated(Instant.now());
            messageUser.setGmtModified(Instant.now());
            messageUsers.add(messageUser);
            if (MessageConstant.PUSH.equals(messageInfo.getPush()) && !MessageReceiveTypeEnum.ALL.getCode().equals(messageInfo.getType())) {
                if (StrUtil.isNotEmpty(userVo.getClientId()) && !cidSet.contains(userVo.getClientId())) {
                    cIds.add(userVo.getClientId());
                }
            }
        }
        messageUserDao.insertByList(messageUsers);
        if (!CollectionUtils.isEmpty(cIds) && messageInfo.getPushTime().compareTo(Instant.now()) <= 0) {
            pushMessage(messageInfo.getTitle(), messageInfo.getMessageAbstract(), String.format(MessageConstant.PushIntentEnum.MESSAGE_DETAIL.getIntentUrl(), messageInfo.getId()), cIds);
            cidSet.addAll(cIds);
        }
    }

    public void pushMessage(String title, String messageAbstract, String format, List<String> cIds) {
        if(!CollectionUtils.isEmpty(cIds)){
            List<String>list=cIds.stream().distinct().collect(Collectors.toList());
            pushMessageToList(title, messageAbstract, format, list);
        }
    }

    public void pushMessageToApp(String msgTitle,String msgText,String transContent){
        messagePushService.pushToAll(msgTitle, msgText, transContent);
    }

    public void pushMessageToList(String msgTitle,String msgText,String transContent,List<String> clientId){
        messagePushService.pushToList(msgTitle, msgText, transContent,clientId);
    }

    private PageBo<UserSearchBo> createUserPageBo(List<String> ids,Integer type,String levelId) {
        PageBo<UserSearchBo> pageBo = new PageBo<>();
        pageBo.setPageSize(100);
        pageBo.setAsc(true);
        pageBo.setSort("gmtCreated");

        UserSearchBo userSearchBo=new UserSearchBo();
        userSearchBo.setProduct(BaseEnum.ProductEnum.FENXIAO.getName());
        if (null != type) {
            userSearchBo.setType(Constant.Area);
        }
        if (StrUtil.isNotEmpty(levelId)) {
            userSearchBo.setUserLevelId(levelId);
        }
        if (!CollectionUtils.isEmpty(ids)) {
            userSearchBo.setIds(ids);
        }
        pageBo.setParam(userSearchBo);
        return pageBo;
    }

    public MessageInfoVo detail(String id){
        MessageInfoVo messageInfoVo=BeanConverUtils.convertBean(messageInfoDao.selectByPrimaryKey(id),MessageInfoVo.class);
        return messageInfoVo;
    }

    public void delete(String messagInfoId){
        messageInfoDao.deleteById(messagInfoId);
        messageUserDao.deleteByMessageId(messagInfoId);
    }

    /**
     * 查询当前用户下的消息列表
     */
    public PageVo<MessageUserListVo> messageList(PageBo<MessageUserBo> bo){
        PageHelper.startPage(bo.getPage(),bo.getPageSize(),MySqlUtil.orderBy(bo.getSort(),bo.isAsc()));
        List<MessageUserList> listByUserId = messageUserDao.getListByUserId(bo.getParam().getUserId());
        PageInfo<MessageUserList> info=new PageInfo<>(listByUserId);
        List<MessageUserListVo> messageUserListVos = BeanConverUtils.convertBeanList(info.getList(), MessageUserListVo.class);
        return new PageVo<>(info.getTotal(),bo.getPage(),bo.getPageSize(),messageUserListVos);
    }

    /**
     * 查看消息详情，更改消息状态为已读
     * @param messageUserBo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MessageInfoDetailVo getMessageDetail(MessageUserBo messageUserBo){
        messageUserDao.updateReadStatus(messageUserBo.getMessageInfoId(),messageUserBo.getUserId());
        return BeanConverUtils.convertBean(messageInfoDao.selectByPrimaryKey(messageUserBo.getMessageInfoId()),MessageInfoDetailVo.class);
    }

    /**
     * 获取该消息下的数据列表
     */
    public PageVo<MessageDataVo> getDataList(PageBo<MessageUserBo> bo){
        PageHelper.startPage(bo.getPage(),bo.getPageSize(),MySqlUtil.orderBy(bo.getSort(),bo.isAsc()));
        PageInfo<MessageUser> messageDataVoPageInfo = new PageInfo<>(messageUserDao.getList(BeanConverUtils.convertBean(bo.getParam(),MessageUser.class)));
        List<MessageDataVo> list = BeanConverUtils.convertBeanList(messageDataVoPageInfo.getList(), MessageDataVo.class);
        return new PageVo<>(messageDataVoPageInfo.getTotal(),bo.getPage(),bo.getPageSize(),list);
    }

    /**
     * 判断该用户是否有未读消息
     */
    public MessageIsReadVo hasUnRead(String userId){
        MessageUser messageUser=new MessageUser();
        MessageIsReadVo messageIsReadVo=new MessageIsReadVo();
        messageUser.setUserId(userId);
        messageUser.setReadStatus(BaseEnum.ReadEnum.UNREAD.getCode());
        if(!messageUserDao.getHasRead(messageUser).isEmpty()){
            messageIsReadVo.setHasReaded(BaseEnum.ReadEnum.READED.getCode());
        }
        return messageIsReadVo;
    }

    public void changeId() {
        List<MessageInfo> list=messageInfoDao.getAll();
        if (!CollectionUtils.isEmpty(list)) {
            Map<String, String> map = new HashMap<>();
            for (MessageInfo messageInfo : list) {
                String id = messageInfo.getId();
                if (id.length() == 11) {
                    long longId = UUIDGenerator.reverseShortUUID(id);
                    map.put(id, String.valueOf(longId));
                }
            }
            if (!CollectionUtils.isEmpty(map)) {
                messageInfoDao.changeId(map);
                messageUserDao.changeMessageInfoId(map);
            }
        }
    }
}
